﻿
Imports osi.root.delegates
Imports osi.root.formation
Imports osi.root.utils
Imports osi.service.argument

Partial Public Class device_wrapper(Of T)
    Private Shared Function conv(ByVal f As Func(Of var, T, T)) As _do_val_val_ref(Of var, T, T, Boolean)
        If f Is Nothing Then
            Return Nothing
        Else
            Return Function(v As var, i As T, ByRef o As T) As Boolean
                       o = f(v, i)
                       Return True
                   End Function
        End If
    End Function

    Public Shared Function register(ByVal v As _do_val_val_ref(Of var, T, T, Boolean)) As Boolean
        If v Is Nothing Then
            Return False
        Else
            ws.emplace_back(v)
            Return True
        End If
    End Function

    Public Shared Function register(ByVal f As Func(Of var, T, T)) As Boolean
        Return register(conv(f))
    End Function

    Public Shared Function register(ByVal type As String,
                                    ByVal v As _do_val_val_ref(Of var, T, T, Boolean)) As Boolean
        If String.IsNullOrEmpty(type) OrElse
           v Is Nothing Then
            Return False
        Else
            wts.generate(type, Function() New vector(Of _do_val_val_ref(Of var, T, T, Boolean))).emplace_back(v)
            Return True
        End If
    End Function

    Public Shared Function register(ByVal type As String, ByVal f As Func(Of var, T, T)) As Boolean
        Return register(type, conv(f))
    End Function

    Public Shared Function bind(ByVal type As String,
                                ByVal v As var,
                                ByRef o As _do_val_ref(Of T, T, Boolean)) As Boolean
        If v Is Nothing Then
            Return False
        Else
            o = Function(i As T, ByRef r As T) As Boolean
                    Return wrap(type, v, i, r)
                End Function
            Return True
        End If
    End Function

    Public Shared Function bind(ByVal v As var,
                                ByRef o As _do_val_val_ref(Of String, T, T, Boolean)) As Boolean
        If v Is Nothing Then
            Return False
        Else
            o = Function(type As String, i As T, ByRef r As T) As Boolean
                    Return wrap(type, v, i, r)
                End Function
            Return True
        End If
    End Function

    Public Shared Function bind(ByVal v As var,
                                ByRef o As _do_val_ref(Of T, T, Boolean)) As Boolean
        If v Is Nothing Then
            Return False
        Else
            o = Function(i As T, ByRef r As T) As Boolean
                    Return wrap(v, i, r)
                End Function
            Return True
        End If
    End Function

    Private Shared Function wrap(ByVal vs As vector(Of _do_val_val_ref(Of var, T, T, Boolean)),
                                 ByVal v As var,
                                 ByVal i As T,
                                 ByRef o As T) As Boolean
        If vs.null_or_empty() Then
            o = i
            Return True
        Else
            For j As Int32 = 0 To vs.size() - 1
                If vs(j)(v, i, o) Then
                    i = o
                Else
                    Return False
                End If
            Next
            Return True
        End If
    End Function

    Public Shared Function wrap(ByVal type As String, ByVal v As var, ByVal i As T, ByRef o As T) As Boolean
        If Not String.IsNullOrEmpty(type) Then
            Dim vs As vector(Of _do_val_val_ref(Of var, T, T, Boolean)) = Nothing
            If wts.get(type, vs) Then
                assert(Not vs Is Nothing)
                If wrap(vs, v, i, o) Then
                    i = o
                Else
                    Return False
                End If
            End If
        End If
        Return wrap(v, i, o)
    End Function

    Public Shared Function wrap(ByVal v As var, ByVal i As T, ByRef o As T) As Boolean
        Return wrap(ws, v, i, o)
    End Function
End Class
